unit Entity;

// ******************************************************************************
interface

// ******************************************************************************

uses
  Field;

type

  // ------------------------------------------------------------------------------
  // TBaseEntity
  // ------------------------------------------------------------------------------

  TEntity = class
  protected
    fNeedSave: boolean;
  private
    fFields: array of TField;
    fToDelete: boolean;
  public
    function isToDelete(): boolean;
    procedure setToDelete(aVal: boolean);
    constructor Create();
    procedure setField(aFieldName: String; aFieldValue: String);
    function toString(): String; virtual;
    procedure serialize(); virtual; abstract;
    procedure freeBaseFields();
    function getByName(aName: String): String;
    function compare(aBaseEntity: TEntity): String;
    destructor Destroy(); override;
    function getPrimaryKeyValue(): String; virtual; abstract;


  end;

  // ******************************************************************************
implementation

// ******************************************************************************

uses
  SysUtils, Dialogs;

// ------------------------------------------------------------------------------
{ TEntity }
// ------------------------------------------------------------------------------

constructor TEntity.Create();
begin
  fNeedSave := false;
  fToDelete := false;
end;

function TEntity.compare(aBaseEntity: TEntity): String;
var
  i: integer;
begin
  Result := '';
  serialize();
  aBaseEntity.serialize();
  for i := 0 to Length(fFields) - 1 do
  begin
    if (aBaseEntity.getByName(fFields[i].getName()) <> fFields[i].getValue())
    then
    begin
      Result := Result + '<field><fieldname> ' + fFields[i].getName() +
        ' </fieldname> ' + '<old>' + aBaseEntity.getByName(fFields[i].getName())
        + '</old> ' + '<new>' + fFields[i].getValue() + '</new> </field>';
    end;

  end;
end;

procedure TEntity.setField(aFieldName: String; aFieldValue: String);
var
  fField: TField;
  i: integer;
  fExists: boolean;
begin
  fExists := false;

  for i := 0 to Length(fFields) - 1 do
  begin
    if (fFields[i].getName() = aFieldName) then
    begin
      fFields[i].setValue(aFieldValue);
      fExists := true;
    end;
  end;

  if (not fExists) then
  begin
    fField := TField.Create(aFieldName, aFieldValue);

    SetLength(fFields, Length(fFields) + 1);
    fFields[High(fFields)] := fField;
  end;

end;

procedure TEntity.setToDelete(aVal: boolean);
begin
  fToDelete := aVal;
end;

function TEntity.toString: String;
begin
  raise Exception.Create(className + ': toString() method is not implemented!');
end;

function TEntity.getByName(aName: String): String;
var
  i: integer;
  fExists: boolean;
begin

  if (Pos('.', aName) <> 0) then
  begin
    Delete(aName, 1, Pos('.', aName));
  end;

  serialize();

  fExists := false;
  Result := '';
  for i := 0 to Length(fFields) - 1 do
  begin
    if (LowerCase(TField(fFields[i]).getName()) = LowerCase(aName)) then
    begin
      Result := TField(fFields[i]).getValue();
      fExists := true;
      break;
    end;
  end;
  if NOT(fExists) then
  begin
    raise Exception.Create(className + ': no field named "' + aName +
      '" found!');
  end;
end;

function TEntity.isToDelete: boolean;
begin
  Result := fToDelete;
end;

procedure TEntity.freeBaseFields;
var
  i: integer;
begin
  for i := Length(fFields) - 1 downto 0 do
  begin
    TField(fFields[i]).Free();
    fFields[i] := nil;
  end;
  SetLength(fFields, 0);
  fFields := nil;
end;

destructor TEntity.Destroy;
begin
  freeBaseFields();
  inherited;
end;

end.
